package com.example.demo.utils;

import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.example.demo.config.ConfigBean;


/*
 * 对接OSS存储，获取上传文件的请求头、请求参数、回调参数 
 * 参考阿里云oss对接地址：https://help.aliyun.com/zh/oss/developer-reference/putobject?scm=20140722.S_help%40%40%E6%96%87%E6%A1%A3%40%4031978.S_BB1%40bl%2BRQW%40ag0%2BBB2%40ag0%2Bhot%2Bos0.ID_31978-RL_putobject-LOC_doc%7EUND%7Eab-OR_ser-V_4-P0_0&spm=a2c4g.11186623.0.i34
 */

 @Component
public class AliyunOss implements OssStorage {
    @Autowired
    private ConfigBean configBean;

    @Override
    public Map<String, String> getHeaders(String objectName) {
        /*
         * 必需参数
         * 1. Authorization
         * 2. Date 此次操作的时间，Date必须为GMT格式，且不能为空。
         * 3. CanonicalizedResource 您希望访问的OSS资源，不能为空。
         */
        Map<String, String> headers = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = sdf.format(new Date());
        
        String verb = "PUT"; // or PUT, POST, DELETE, etc.
        String contentMD5 = ""; // 非必须 ，如果有请按照oss文档传入
        String contentType = ""; // 非必须 ，如果有请按照oss文档传入
        String canonicalizedResource = configBean.getBucketName() + objectName; // bucketName: 您的Bucket名称，objectName: 您的Object名称

        String stringToSign = verb + "\n"
            + contentMD5 + "\n"
            + contentType + "\n"
            + date + "\n"
            + canonicalizedResource;


        // 生成签名
        String signature = generateSignature( configBean.getAccessKeySecret(), stringToSign);
        headers.put("content-type", contentType);
        headers.put("Authorization", "OSS " + configBean.getAccessKeyId() + ":" + signature);
        headers.put("Date", date);
        headers.put("CanonicalizedResource",  configBean.getBucketName());  // bucketName: 您的Bucket名称，objectName: 您的Object名称
        return headers;
    }

    @Override
    public Map<String, String> getParams() {
        /*
         * 如有需要，完成上传必须的参数
         */
        return null;
    }

    @Override
    public Map<String, String> getSendBackParams() {
        /*
         * 如有需要，完成上传完成后的回调参数
         */
        return null;
    }

    private String generateSignature(String accessKeySecret, String stringToSign) {
        try {
            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec secretKeySpec = new SecretKeySpec(accessKeySecret.getBytes(), "HmacSHA1");
            mac.init(secretKeySpec);
            byte[] rawHmac = mac.doFinal(stringToSign.getBytes());
            return Base64.getEncoder().encodeToString(rawHmac);
        } catch (Exception e) {
            throw new RuntimeException("Unable to calculate a request signature: " + e.getMessage(), e);
        }
    }
}
